package com.fpd.tools;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

import com.fpd.model.entity.EnterMoneyBackRecord;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fpd.model.entity.Metadata;
import cn.hutool.core.io.FileUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.multipart.MultipartFile;

/**
 * @desc 读取Excel的工具类
 * @author wujiangbo
 * @date 2019年11月11日 下午2:42:32
 */
public class ExcelUtils {
	static Pattern pattern = Pattern.compile("(-?\\d+\\.?\\d*)[Ee]{1}[\\+-]?[0-9]*");
	static DecimalFormat ds = new DecimalFormat("0");

	public final static Logger log = LoggerFactory.getLogger(ExcelUtils.class);

	public static void main(String[] args) {
//		String file_path = "D:/test.xls";
		String file_path = "E:\\hengcheng\\excle\\metadata_excel.xls";
//		String file_path = "D:/数据表头模板.xlsx";

//		test1(file_path);
		test2(file_path);
	}

	public static void test1(String file_path) {
		List<List<Object>> data_list = ExcelUtils.readExcel(file_path);
		for (int i = 0; i < data_list.size(); i++) {
			List<Object> cell_list = data_list.get(i);
			System.out.println(cell_list.size());
			System.out.println(cell_list.toString());
		}
	}

	public static void test2(String file_path) {
		ExcelReader reader = ExcelUtil.getReader(FileUtil.file(file_path), 0);
		List<Metadata> obj_list = reader.readAll(Metadata.class);
		System.out.println("总行数：" + obj_list.size());
		for (int i = 0; i < obj_list.size(); i++) {
			System.out.println(obj_list.get(i).toString());
		}
	}

	/**
	 * @desc 利用HUtool的ExcelUtil读取Excel文件
	 * @author wujiangbo
	 * @date 2019年11月11日 下午2:44:02
	 * @param file_path
	 * @return List<List<Object>>
	 */
	public static List<List<Object>> readExcel(String file_path) {
		List<List<Object>> return_list = null;
		try {
			// 0：表示第一个Sheet页
			ExcelReader reader = ExcelUtil.getReader(FileUtil.file(file_path), 0);
//			int columnCount = reader.getColumnCount(0);
//			int physicalRowCount = reader.getPhysicalRowCount();
//			System.out.println("总列数："+columnCount);
//			System.out.println("有记录的行数："+physicalRowCount);
			// true:忽略空行;1:从第二行开始读取
			return_list = reader.setIgnoreEmptyRow(true).read(1);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("HUtool--ExcelUtil工具类读取Excel文件，发生异常：" + e.getLocalizedMessage());
		}
		return return_list;
	}

	/**
	 *
	 * 读取excel 封装成集合 该程序需要传入一份excel 和excel的列数 行数由程序自动检测 注意：该方法统计的行数是默认第一行为title
	 * 不纳入统计的
	 *
	 * @return
	 *
	 */
	public static List<List> readExcelByFilePath(String filePath) {

		// int column = 5;//column表示excel的列数

		List<List> list = new ArrayList<List>();

		try {
			// 建需要读取的excel文件写入stream
			HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(filePath));
			// 指向sheet下标为0的sheet 即第一个sheet 也可以按在sheet的名称来寻找
			HSSFSheet sheet = workbook.getSheetAt(0);
			// 获取sheet1中的总行数
			int rowTotalCount = sheet.getLastRowNum();
			// 获取总列数
			int columnCount = sheet.getRow(0).getPhysicalNumberOfCells();

			System.out.println("行数为：" + rowTotalCount + "列数为：" + columnCount);

			for (int i = 1; i <= rowTotalCount; i++) {
				// 获取第i列的row对象
				HSSFRow row = sheet.getRow(i);
//				row.getCell(0).getCellType();
				ArrayList<String> listRow = new ArrayList<String>();
				// 合同号为空，该栏为空
				if (row.getCell(1) == null || row.getCell(1).toString().equals("")) {
					continue;
				}

				for (int j = 0; j < columnCount; j++) {
					// 下列步骤为判断cell读取到的数据是否为null 如果不做处理 程序会报错
					String cell = ExcelUtils.getCellValue(row.getCell(j));
					listRow.add(cell);
					// 如果未null则加上""组装成非null的字符串
//                    if(row.getCell(j) == null){
////                        cell = row.getCell(j);
//                        listRow.add("");
//                        //如果读取到额cell不为null 则直接加入	listRow集合
//                    }else{
//                        cell = row.getCell(j).toString();
//                        listRow.add(cell);
//                    }
					// 在第i列 依次获取第i列的第j个位置上的值 %15s表示前后间隔15个字节输出
//                    System.out.printf("%15s", cell);

				}
				list.add(listRow);
			}

		} catch (FileNotFoundException e) {

			e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		}

		return list;
	}

	public static List<List> readMetaExcelByFilePath(String filePath) {

		// int column = 5;//column表示excel的列数

		List<List> list = new ArrayList<List>();
		for (int i = 0; i < list.size(); i++) {

			int size = list.size();
			for (int j = 0; j < size; j++) {

			}
		}

		try {
			// 建需要读取的excel文件写入stream
			HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(filePath));
			// 指向sheet下标为0的sheet 即第一个sheet 也可以按在sheet的名称来寻找
			HSSFSheet sheet = workbook.getSheetAt(0);
			// 获取sheet1中的总行数
			int rowTotalCount = sheet.getLastRowNum();
			// 获取总列数
			int columnCount = sheet.getRow(0).getPhysicalNumberOfCells();

			System.out.println("行数为：" + rowTotalCount + "列数为：" + columnCount);
			HSSFRow row = null;
			for (int i = 1; i <= rowTotalCount; i++) {
				// 获取第i列的row对象
				row = sheet.getRow(i);
				ArrayList<String> listRow = new ArrayList<String>();
				// 合同号为空，该栏为空
				if (row.getCell(2) == null || row.getCell(2).toString().equals("")) {
					continue;
				}
				for (int j = 0; j < columnCount; j++) {
					// 下列步骤为判断cell读取到的数据是否为null 如果不做处理 程序会报错
					String cell = ExcelUtils.getCellValue(row.getCell(j));
					listRow.add(cell);
				}
				listRow.add(String.valueOf(i+1));
				list.add(listRow);
			}

		} catch (FileNotFoundException e) {

			e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		}

		return list;
	}


	//js直接读取文件流
	public static List<List> readMetaExcelByFileStream(MultipartFile file, RedisTemplate redisTemplate, String verifyToken) {

		// int column = 5;//column表示excel的列数

		List<List> list = new ArrayList<List>();

		try {
			InputStream inputStream = file.getInputStream();
			// 建需要读取的excel文件写入stream
			HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
			// 指向sheet下标为0的sheet 即第一个sheet 也可以按在sheet的名称来寻找
			HSSFSheet sheet = workbook.getSheetAt(0);
			// 获取sheet1中的总行数
			int rowTotalCount = sheet.getLastRowNum();

			// 获取总列数
			int columnCount = sheet.getRow(0).getPhysicalNumberOfCells();
			//(最多)插入19个节点，在这些节点向redis中写入进度
			int step = (int)Math.ceil(rowTotalCount/19.0);
			List<Integer> nodes = new ArrayList<Integer>();
			System.out.println("行数为：" + rowTotalCount + "列数为：" + columnCount);
			HSSFRow row = null;
			for (int i = 1; i <= rowTotalCount; i++) {

				/**
				 * 假设有190行数据，那么步调为10，在第1,11,21,31...181行将进度写入redis
				 * 假如只有5行数据，那么步调为1，每一行都会将进度写入redis，只是进度会是1,2,3,4,5,不会出现6-19
				 * 步调设置成整数，也可能因此丢失末几位进度，比如总共一百条数据，在第100条时进度为17
				 */
				if(i==1){
					//写入初始进度
					redisTemplate.opsForValue().set("pregress_bar:"+verifyToken,1,120, TimeUnit.SECONDS);
					nodes.add(1+step);
				}
				//从计数器中取出下一个写入的节点
				int nextNode = nodes.get(nodes.size()-1);
				if(i>1 && (i-1)<nextNode && i>=nextNode){
					//写入第i个进度
					redisTemplate.opsForValue().set("pregress_bar:"+verifyToken,nodes.size()+1,120, TimeUnit.SECONDS);
					nodes.add(i+step);
				}

				// 获取第i列的row对象
				row = sheet.getRow(i);
				// 如果导入文件中存在空行,跳过
				if(row==null) continue;

				ArrayList<String> listRow = new ArrayList<String>();
				// 合同号为空，该栏为空
//				if (row.getCell(2) == null || row.getCell(2).toString().equals("")) {
//					continue;
//				}
				for (int j = 0; j < columnCount; j++) {
					// 下列步骤为判断cell读取到的数据是否为null 如果不做处理 程序会报错
					String cell = ExcelUtils.getCellValue(row.getCell(j));
					listRow.add(cell);
				}
				listRow.add(String.valueOf(i+1));
				list.add(listRow);
			}

		} catch (FileNotFoundException e) {

			e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		}

		return list;
	}

	public static List<List> readMetadataExcelByFilePath(String filePath,List<String> resultList) {

		// int column = 5;//column表示excel的列数

		List<List> list = new ArrayList<List>();

		try {
			// 建需要读取的excel文件写入stream
			HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(filePath));
			// 指向sheet下标为0的sheet 即第一个sheet 也可以按在sheet的名称来寻找
			HSSFSheet sheet = workbook.getSheetAt(0);
			// 获取sheet1中的总行数
			int rowTotalCount = sheet.getLastRowNum();
			// 获取总列数
			int columnCount = sheet.getRow(0).getPhysicalNumberOfCells();
			System.out.println("行数为：" + rowTotalCount + "列数为：" + columnCount);
			//判断日期el表达式
//			String eL ="(\\d{4})/(\\d{2})/(\\d{2})";
//			Pattern p = Pattern.compile(eL);
			for (int i = 1; i < rowTotalCount; i++) {
				Boolean flag = false;
				// 获取第i列的row对象
				HSSFRow row = sheet.getRow(i);
//				row.getCell(0).getCellType();
				ArrayList<String> listRow = new ArrayList<String>();
				// 合同号为空，该栏为空
				if (row.getCell(2) == null || row.getCell(2).toString().equals("")) {
					continue;
				}
				flag = getaDataBoolean(resultList, i, flag, row);
				if (flag){
					continue;
				}
				for (int j = 0; j <= columnCount; j++) {
//					listRow.add((i+1)+"");
					// 下列步骤为判断cell读取到的数据是否为null 如果不做处理 程序会报错
					String cell = ExcelUtils.getCellValue(row.getCell(j));
					listRow.add(cell);
					// 如果未null则加上""组装成非null的字符串
//                    if(row.getCell(j) == null){
////                        cell = row.getCell(j);
//                        listRow.add("");
//                        //如果读取到额cell不为null 则直接加入	listRow集合
//                    }else{
//                        cell = row.getCell(j).toString();
//                        listRow.add(cell);
//                    }
					// 在第i列 依次获取第i列的第j个位置上的值 %15s表示前后间隔15个字节输出
//                    System.out.printf("%15s", cell);
				}
				list.add(listRow);
			}

		} catch (FileNotFoundException e) {

			e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		}

		return list;
	}

	private static Boolean getaDataBoolean(List<String> resultList, int i, Boolean flag, HSSFRow row) {
		String cell0 = row.getCell(0).toString();
		String cell3 = row.getCell(3).toString();
		String cell1 = row.getCell(1).toString();
		String cell5 = row.getCell(5).toString();
		String cell7 = row.getCell(7).toString();
		String cell9 = row.getCell(9).toString();
		String cell17 = row.getCell(17).toString();
		String cell18 = row.getCell(18).toString();
		String cell19 = row.getCell(19).toString();
		String cell20 = row.getCell(20).toString();
		String cell21 = row.getCell(21).toString();
		String cell24 = row.getCell(24).toString();

		if (StringUtils.isNull(cell0)) {
			resultList.add("第"+(i+1)+"行委案时间不能为空");
			flag = true;
		}
		if (StringUtils.isNull(cell3)) {
			resultList.add("第"+(i+1)+"行客户号不能为空");
			flag = true;
		}
		if (StringUtils.isNull(cell1)) {
			resultList.add("第"+(i+1)+"行计划收回时间不能为空");
			flag = true;
		}
		if (StringUtils.isNull(cell5)) {
			resultList.add("第"+(i+1)+"行客户姓名不能为空");
			flag = true;
		}
		if (StringUtils.isNull(cell7)) {
			resultList.add("第"+(i+1)+"行身份证号不能为空");
			flag = true;
		}
		if (StringUtils.isNull(cell9)) {
			resultList.add("第"+(i+1)+"行案件类型不能为空");
			flag = true;
		}
		if (StringUtils.isNull(cell17)) {
			resultList.add("第"+(i+1)+"行贷款总额不能为空");
			flag = true;
//					throw new ParameterException("第"+(1+1)+"行贷款总额不能为空");
		}
		if (StringUtils.isNull(cell18)) {
			resultList.add("第"+(i+1)+"行期数不能为空");
			flag = true;
		}
		if (StringUtils.isNull(cell19)) {
			resultList.add("第"+(i+1)+"行行逾期天数不能为空");
			flag = true;
		}
		if (StringUtils.isNull(cell20)) {
			resultList.add("第"+(i+1)+"行逾期金额不能为空");
			flag = true;
		}
		if (StringUtils.isNull(cell21)) {
			resultList.add("第"+(i+1)+"行剩余总欠款不能为空");
			flag = true;
		}
		if (StringUtils.isNull(cell24)) {
			resultList.add("第"+(i+1)+"行合同生效日期不能为空");
			flag = true;
		}
		return flag;
	}

	/**
	 *
	 * 读取excel 封装成集合 该程序需要传入一份excel 和excel的列数 行数由程序自动检测 注意：该方法统计的行数是默认第一行为title
	 * 不纳入统计的
	 *
	 * @return
	 *
	 */
	public static List<List> readMoneyBack(String filePath) {

		// int column = 5;//column表示excel的列数

		List<List> list = new ArrayList<List>();

		try {
			// 建需要读取的excel文件写入stream
			HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(filePath));
			// 指向sheet下标为0的sheet 即第一个sheet 也可以按在sheet的名称来寻找
			HSSFSheet sheet = workbook.getSheetAt(0);
			// 获取sheet1中的总行数
			int rowTotalCount = sheet.getLastRowNum();
			// 获取总列数
			int columnCount = sheet.getRow(0).getPhysicalNumberOfCells();

			System.out.println("行数为：" + rowTotalCount + "列数为：" + columnCount);

			for (int i = 1; i <= rowTotalCount; i++) {
				// 获取第i列的row对象
				HSSFRow row = sheet.getRow(i);
//				row.getCell(0).getCellType();
				ArrayList<String> listRow = new ArrayList<String>();
				// 合同号为空，该栏为空
				if (row.getCell(2) == null || row.getCell(2).toString().equals("")) {
					continue;
				}
				for (int j = 0; j < columnCount; j++) {
					// 下列步骤为判断cell读取到的数据是否为null 如果不做处理 程序会报错
					String cell = ExcelUtils.getCellValue(row.getCell(j));
					listRow.add(cell);
					// 如果未null则加上""组装成非null的字符串
//                    if(row.getCell(j) == null){
////                        cell = row.getCell(j);
//                        listRow.add("");
//                        //如果读取到额cell不为null 则直接加入	listRow集合
//                    }else{
//                        cell = row.getCell(j).toString();
//                        listRow.add(cell);
//                    }
					// 在第i列 依次获取第i列的第j个位置上的值 %15s表示前后间隔15个字节输出
//                    System.out.printf("%15s", cell);

				}
				list.add(listRow);
			}

		} catch (FileNotFoundException e) {

			e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		}

		return list;
	}

	public static String getCellValue(HSSFCell cell) {
		String value = "";
		if (cell != null) {
			switch (cell.getCellType()) {
			case FORMULA:
				try {
					value = String.valueOf(cell.getNumericCellValue());
				} catch (IllegalStateException e) {
					value = String.valueOf(cell.getRichStringCellValue());
				}
				break;
			case NUMERIC:
				if (HSSFDateUtil.isCellDateFormatted(cell)) {// 处理日期格式、时间格式
					SimpleDateFormat sdf = null;
					if (cell.getCellStyle().getDataFormat() == HSSFDataFormat.getBuiltinFormat("h:mm")) {
						sdf = new SimpleDateFormat("HH:mm");
					} else {// 日期
						sdf = new SimpleDateFormat("yyyy/MM/dd");
					}
					Date date = cell.getDateCellValue();
					value = sdf.format(date);
				} else if (cell.getCellStyle().getDataFormat() == 58) {
					// 处理自定义日期格式：m月d日(通过判断单元格的格式id解决，id的值是58)
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
					double num = cell.getNumericCellValue();
					Date date = org.apache.poi.ss.usermodel.DateUtil.getJavaDate(num);
					value = sdf.format(date);
				} else {
					if (isENum(String.valueOf(cell.getNumericCellValue()))) {
						value = ds.format(Double.parseDouble(String.valueOf(cell.getNumericCellValue()))).trim();
					}else {
						cell.setCellType(CellType.STRING);
						value = String.valueOf(cell.getStringCellValue());
					}
				}
				break;
			case STRING:
				value = String.valueOf(cell.getRichStringCellValue());
				break;
			}
		}
		return value;
	}
	static boolean isENum(String input) {//判断输入字符串是否为科学计数法
		return pattern.matcher(input).matches();
	}

	public static List<EnterMoneyBackRecord> readMoneyBackRecordExcelByFileStream(MultipartFile file) {
		List<EnterMoneyBackRecord> list = new ArrayList<>();
		try {
			InputStream inputStream = file.getInputStream();
			HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
			HSSFSheet sheet = workbook.getSheetAt(0);

			int rowTotalCount = sheet.getLastRowNum();
			// 获取总列数
			int columnCount = sheet.getRow(0).getPhysicalNumberOfCells();
			HSSFRow row = null;
			for (int i = 1; i <= rowTotalCount; i++) {

				// 获取第i列的row对象
				row = sheet.getRow(i);
				// 合同号为空，跳过
				if (row.getCell(3) == null || row.getCell(3).toString().equals("")) {
					continue;
				}
				EnterMoneyBackRecord enterMoneyBackRecord = new EnterMoneyBackRecord();
//				enterMoneyBackRecord.setCaseBeginTime(new SimpleDateFormat("yyyy/MM/dd").parse(ExcelUtils.getCellValue(row.getCell(0))));//委托日期
//				enterMoneyBackRecord.setCaseEndTime(new SimpleDateFormat("yyyy/MM/dd").parse(ExcelUtils.getCellValue(row.getCell(1))));//结案日期
				enterMoneyBackRecord.setCustName(ExcelUtils.getCellValue(row.getCell(0)));//客户姓名
				enterMoneyBackRecord.setContractNumber(ExcelUtils.getCellValue(row.getCell(1)));//合同号
				enterMoneyBackRecord.setYuqiDayQuantum(ExcelUtils.getCellValue(row.getCell(2)));//逾期阶段
				enterMoneyBackRecord.setBackTime(new SimpleDateFormat("yyyy/MM/dd").parse(ExcelUtils.getCellValue(row.getCell(3))));//还款时间
				enterMoneyBackRecord.setBackTimeQuantum("上午".equals(ExcelUtils.getCellValue(row.getCell(4)))?1:("下午".equals(ExcelUtils.getCellValue(row.getCell(4)))?2:3));//还款时间段
				enterMoneyBackRecord.setBackType("对公".equals(ExcelUtils.getCellValue(row.getCell(5)))?1:2);//还款类型
				enterMoneyBackRecord.setEnterAmount(new BigDecimal(ExcelUtils.getCellValue(row.getCell(6))));//还款金额
				enterMoneyBackRecord.setCustomerCare(ExcelUtils.getCellValue(row.getCell(7)));//客服
				list.add(enterMoneyBackRecord);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}
}
